{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([True, True, True, True])\n"
     ]
    }
   ],
   "source": [
    "# torch 会存储计算图，并自动求导，下面演示一下 y = 2x的转置乘x的求导，我们知道答案是4x\n",
    "x = torch.arange(4.0,requires_grad=True)\n",
    "# x.requires_grad(True)\n",
    "y = 2*torch.dot(x,x)\n",
    "y.backward()\n",
    "print(x.grad == 4*x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([True, True, True, True])\n"
     ]
    }
   ],
   "source": [
    "# 尝试一下求和\n",
    "x.grad.zero_() # 清除上一步的计算\n",
    "y = x.sum() # y=x1+x2+...+x4\n",
    "y.backward()\n",
    "print(x.grad == torch.ones(4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([0., 2., 4., 6.])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 结果是张量的，在深度学习中，一般不会对向量求导，这里用sum()求标量后再求导\n",
    "x.grad.zero_()\n",
    "y = x*x\n",
    "y.sum().backward()\n",
    "x.grad"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([0., 1., 4., 9.])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 取消某个变量的跟踪，比如我们要计算一个常熟，和x相关但我们不希望u参与计算图\n",
    "x.grad.zero_()\n",
    "y=x*x\n",
    "u = y.detach() # 这一步就相当于说u当成一个常数\n",
    "z = u*x\n",
    "z.sum().backward()\n",
    "x.grad"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([0., 2., 4., 6.])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 由于记录了y的计算过程，因此还可以对y求导\n",
    "x.grad.zero_()\n",
    "y.sum().backward()\n",
    "x.grad\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([ 1.0000,  0.5403, -0.4161, -0.9900])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import math\n",
    "x.grad.zero_()\n",
    "y = x.sin()\n",
    "y.sum().backward()\n",
    "x.grad"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
